package com.xhwl.logistics.service.business;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xhwl.logistics.bo.cent.ProjectBO;
import com.xhwl.logistics.converter.mapstruct.VehicleDataPushConverter;
import com.xhwl.logistics.dto.push.CarInHuaWeiIotDTO;
import com.xhwl.logistics.dto.push.CarInKeTopDTO;
import com.xhwl.logistics.dto.push.CarOutHuaWeiIotDTO;
import com.xhwl.logistics.dto.push.CarOutKeTopDTO;
import com.xhwl.logistics.dto.push.CarPayKeTopDTO;
import com.xhwl.logistics.entity.VehicleAccessRecord;
import com.xhwl.logistics.entity.VehiclePayRecord;
import com.xhwl.logistics.service.impl.VehicleAccessRecordServiceImpl;
import com.xhwl.logistics.service.impl.VehiclePayRecordServiceImpl;
import com.xhwl.logistics.service.impl.redis.VehicleExceptionRedisServiceImpl;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

//@Service
public class VehicleDataPushBusinessService {

    @Autowired
    private VehicleAccessRecordServiceImpl vehicleAccessRecordService;

    @Autowired
    private VehiclePayRecordServiceImpl vehiclePayRecordService;

    @Autowired
    private VehicleDataPushConverter vehicleDataPushConverter;

    @Autowired
    private VehicleExceptionRedisServiceImpl vehicleExceptionRedisService;

    private Wrapper<VehicleAccessRecord> conditionForQueryAccessRecordIn(String recordId, Integer projectId, String parkId) {
        LambdaQueryWrapper<VehicleAccessRecord> queryWrapper = Wrappers.lambdaQuery();
        return queryWrapper
                .eq(VehicleAccessRecord::getRecordId, recordId)
                .eq(VehicleAccessRecord::getProjectId, projectId)
                .eq(VehicleAccessRecord::getParkId, parkId);
    }

    public void huaWeiIotCarIn(List<CarInHuaWeiIotDTO> carInHuaWeiIotDTOList, ProjectBO projectBO) {
        List<VehicleAccessRecord> vehicleAccessRecordList = vehicleDataPushConverter.toVehicleAccessRecordList(carInHuaWeiIotDTOList, projectBO);
        /**
         * 添加过滤条件，根据recordId进行过滤
         */
        List<VehicleAccessRecord> vehicleAccessRecordFromCent = vehicleAccessRecordService.list(new LambdaQueryWrapper<VehicleAccessRecord>().eq(VehicleAccessRecord::getProjectId, projectBO.getProjectId()));
        List<VehicleAccessRecord> vehicleAccessRecords = huaWeiIotFilterAccessRecord(vehicleAccessRecordFromCent, vehicleAccessRecordList);
        vehicleAccessRecordService.saveBatch(vehicleAccessRecords);
    }

    /**
     * 根据recordId来过滤出行记录
     * @param centVehicleAccessRecords
     * @param thirdVehicleAccessRecords
     */
    public List<VehicleAccessRecord> huaWeiIotFilterAccessRecord(List<VehicleAccessRecord> centVehicleAccessRecords,List<VehicleAccessRecord> thirdVehicleAccessRecords){
        LinkedList<VehicleAccessRecord> thirdvehicleAccessRecordList = new LinkedList<>();
        LinkedList<VehicleAccessRecord> centVehicleAccessRecordList = new LinkedList<>();

        List<VehicleAccessRecord> vehicleAccessRecords = new LinkedList<>();
        //去除thirdVehicleAccessRecords中的重复信息
        for (VehicleAccessRecord thirdVehicleAccessRecord : thirdVehicleAccessRecords) {
            VehicleAccessRecord vehicleAccessRecord = thirdvehicleAccessRecordList.stream().filter(s -> {
                if (StringUtils.equals(s.getRecordId(), thirdVehicleAccessRecord.getRecordId())) {
                    return true;
                } else {
                    return false;
                }
            }).findAny().orElse(null);
            if(vehicleAccessRecord==null){
                thirdvehicleAccessRecordList.add(thirdVehicleAccessRecord);
            }
        }
        //去除centVehicleAccessRecords中的重复信息
        for (VehicleAccessRecord centVehicleAccessRecord : centVehicleAccessRecords) {
            VehicleAccessRecord vehicleAccessRecord = centVehicleAccessRecordList.stream().filter(s -> {
                if (StringUtils.equals(s.getRecordId(), centVehicleAccessRecord.getRecordId())) {
                    return true;
                } else {
                    return false;
                }
            }).findAny().orElse(null);
            if(vehicleAccessRecord==null){
                centVehicleAccessRecordList.add(centVehicleAccessRecord);
            }
        }
        List<String> recordIdFromCent = centVehicleAccessRecordList.stream().map(s -> s.getRecordId()).collect(Collectors.toList());

        List<String> recordIdFromHuaWeiIot = thirdvehicleAccessRecordList.stream().map(s -> s.getRecordId()).collect(Collectors.toList());
        Map<String, VehicleAccessRecord> mapForHuaWeiIot = thirdvehicleAccessRecordList.stream().collect(Collectors.toMap(s -> s.getRecordId(), Function.identity()));

        List<String> add = ListUtils.subtract(recordIdFromHuaWeiIot, recordIdFromCent);
        if(!add.isEmpty()){
            vehicleAccessRecords = add.stream().map(mapForHuaWeiIot::get).collect(Collectors.toList());
        }
        return vehicleAccessRecords;
    }

    @Transactional
    public void huaWeiIotCarOut(List<CarOutHuaWeiIotDTO> carOutHuaWeiIotDTOList, ProjectBO projectBO) {
        List<String> recordIdList = carOutHuaWeiIotDTOList.stream()
                .map(CarOutHuaWeiIotDTO::getCaroutInRecordId).collect(Collectors.toList());
        LambdaQueryWrapper<VehicleAccessRecord> queryWrapper = Wrappers.lambdaQuery();

        List<VehicleAccessRecord> vehicleAccessRecordList = vehicleAccessRecordService
                .list(queryWrapper.in(VehicleAccessRecord::getRecordId, recordIdList));
        Map<String, Integer> temp = vehicleAccessRecordList.stream().collect(Collectors.toMap(VehicleAccessRecord::getRecordId, VehicleAccessRecord::getId));

        List<VehicleAccessRecord> add = new ArrayList<>();
        List<VehicleAccessRecord> update = new ArrayList<>();
        List<VehiclePayRecord> pay = new ArrayList<>();
        for (CarOutHuaWeiIotDTO carOutHuaWeiIotDTO : carOutHuaWeiIotDTOList) {
            Integer id = temp.get(carOutHuaWeiIotDTO.getCaroutInRecordId());
            if (Objects.isNull(id)) {
                add.add(vehicleDataPushConverter.toVehicleAccessRecord(carOutHuaWeiIotDTO, projectBO));
            } else {
                update.add(vehicleDataPushConverter.toVehicleAccessRecord(carOutHuaWeiIotDTO, id));
            }

            pay.add(vehicleDataPushConverter.toVehiclePayRecordHuaWeiIot(carOutHuaWeiIotDTO, projectBO.getProjectId()));
        }

        if (!add.isEmpty()) {
            vehicleAccessRecordService.saveBatch(add);
        }
        if (!update.isEmpty()) {
            vehicleAccessRecordService.updateBatchById(update);
        }
        if (!pay.isEmpty()) {
            /**
             * 添加过滤条件，根据billId进行过滤
             */
            List<VehiclePayRecord> vehiclePayRecords = vehiclePayRecordService.list(new LambdaQueryWrapper<VehiclePayRecord>().eq(VehiclePayRecord::getProjectId, projectBO.getProjectId()));
            List<VehiclePayRecord> vehiclePayRecordsList = huaWeiIotFilterPayRecord(vehiclePayRecords, pay);
            vehiclePayRecordService.saveBatch(vehiclePayRecordsList);
        }
    }

    /**
     * 根据billId来过滤付费记录
     * @param centVehiclePayRecords
     * @param thirdVehiclePayRecords
     */
    public List<VehiclePayRecord> huaWeiIotFilterPayRecord(List<VehiclePayRecord> centVehiclePayRecords,List<VehiclePayRecord> thirdVehiclePayRecords){
        LinkedList<VehiclePayRecord> thirdVehiclePayRecordList = new LinkedList<>();
        LinkedList<VehiclePayRecord> centVehiclePayRecordList = new LinkedList<>();

        List<VehiclePayRecord> vehiclePayRecords = new LinkedList<>();
        //去除thirdVehiclePayRecords中的重复信息
        for (VehiclePayRecord  thirdVehiclePayRecord: thirdVehiclePayRecords) {
            VehiclePayRecord vehiclePayRecord = thirdVehiclePayRecordList.stream().filter(s -> {
                if (StringUtils.equals(s.getAccessRecordId(), thirdVehiclePayRecord.getAccessRecordId())) {
                    return true;
                } else {
                    return false;
                }
            }).findAny().orElse(null);
            if(vehiclePayRecord==null){
                thirdVehiclePayRecordList.add(thirdVehiclePayRecord);
            }
        }
        //去除centVehiclePayRecords中的重复信息
        for (VehiclePayRecord  centVehiclePayRecord: centVehiclePayRecords) {
            VehiclePayRecord vehiclePayRecord = centVehiclePayRecordList.stream().filter(s -> {
                if (StringUtils.equals(s.getAccessRecordId(), centVehiclePayRecord.getAccessRecordId())) {
                    return true;
                } else {
                    return false;
                }
            }).findAny().orElse(null);
            if(vehiclePayRecord==null){
                centVehiclePayRecordList.add(centVehiclePayRecord);
            }
        }
        List<String> recordIdFromCent = centVehiclePayRecordList.stream().map(s -> s.getAccessRecordId()).collect(Collectors.toList());

        List<String> recordIdFromHuaWeiIot = thirdVehiclePayRecordList.stream().map(s -> s.getAccessRecordId()).collect(Collectors.toList());
        Map<String, VehiclePayRecord> mapForHuaWeiIot = thirdVehiclePayRecordList.stream().collect(Collectors.toMap(s -> s.getAccessRecordId(), Function.identity()));

        List<String> add = ListUtils.subtract(recordIdFromHuaWeiIot, recordIdFromCent);
        if(!add.isEmpty()){
            vehiclePayRecords = add.stream().map(mapForHuaWeiIot::get).collect(Collectors.toList());
        }
        return vehiclePayRecords;
    }

    public void keTopCarIn(CarInKeTopDTO carInKeTopDTO, ProjectBO projectBO) {
        VehicleAccessRecord vehicleAccessRecord = vehicleDataPushConverter.toVehicleAccessRecordByKeTop(carInKeTopDTO, projectBO);
        //对出行记录进行去重处理，即存在就更新，不存在就新增
        List<VehicleAccessRecord> vehicleAccessRecordList = vehicleAccessRecordService.list(new LambdaQueryWrapper<VehicleAccessRecord>().eq(VehicleAccessRecord::getProjectId, projectBO.getProjectId())
                .eq(VehicleAccessRecord::getRecordId, carInKeTopDTO.getTrafficId()));
        if(vehicleAccessRecordList.isEmpty()){
            vehicleAccessRecordService.save(vehicleAccessRecord);
        }else{
            vehicleAccessRecord.setId(vehicleAccessRecordList.get(0).getId());
            vehicleAccessRecordService.updateById(vehicleAccessRecord);
        }
    }

    public void keTopCarOut(CarOutKeTopDTO carOutKeTopDTO, ProjectBO projectBO) {
        List<VehicleAccessRecord> vehicleAccessRecordList = vehicleAccessRecordService.list(conditionForQueryAccessRecordIn(carOutKeTopDTO.getTrafficId(), projectBO.getProjectId(), String.valueOf(carOutKeTopDTO.getParkId())));
        if (vehicleAccessRecordList.isEmpty()) {
            VehicleAccessRecord vehicleAccessRecord = vehicleDataPushConverter.toVehicleAccessRecordByKeTop(carOutKeTopDTO, projectBO);
            vehicleAccessRecordService.save(vehicleAccessRecord);
        } else {
            if (1==vehicleAccessRecordList.size()) {
                Integer id = vehicleAccessRecordList.get(0).getId();
                VehicleAccessRecord vehicleAccessRecord = vehicleDataPushConverter.toVehicleAccessRecordByKeTop(carOutKeTopDTO, id);
                vehicleAccessRecordService.updateById(vehicleAccessRecord);
            } else {
                vehicleExceptionRedisService.exceptionMessage("ke-top-data-push-car-out", "推送的车辆出场记录的出入关联id在已入库的车辆进出记录中，找到了多个，重复的多个关联id无法进一步处理");
            }
        }
    }

    public void keTopCarPay(CarPayKeTopDTO carPayKeTopDTO, Integer projectId) {
        VehiclePayRecord vehiclePayRecord = vehicleDataPushConverter.toVehiclePayRecord(carPayKeTopDTO, projectId);
        //对缴费记录进行去重处理，即存在就更新，不存在就新增
        List<VehiclePayRecord> vehiclePayRecordList = vehiclePayRecordService.list(new LambdaQueryWrapper<VehiclePayRecord>().eq(VehiclePayRecord::getProjectId, projectId)
                .eq(VehiclePayRecord::getAccessRecordId, carPayKeTopDTO.getBillId()));
        if(vehiclePayRecordList.isEmpty()){
            vehiclePayRecordService.save(vehiclePayRecord);
        }else{
            vehiclePayRecord.setId(vehiclePayRecordList.get(0).getId());
            vehiclePayRecordService.updateById(vehiclePayRecord);
        }
    }

}
